package org.hackystat.ui.hackerrific.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowCloseListener;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalSplitPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * A widget to view realtime Hackystat sensor data.
 * @author David J. Nickles
 */
public class TwitterWidget implements EntryPoint, WindowCloseListener, ClickListener {
  
  /** {@literal} PRCERRORNAME name for RPC errors. */  
  private static final String PRCERRORNAME = "Error on Version RPC"; 
  /** {@literal} WIDGETSLOT name for RPC errors. */  
  private static final String WIDGETSLOT = "widget"; 
  
  /* Widget UI elements */
  private Boolean settingsFaceUp;
  private EntryPanel entryPanel;
  private SettingsPanel settingsPanel;
  private StatusesPanel statusesPanel;
  private VerticalSplitPanel splitPane;
  
  /**
   * Applies a Scriptaculous effect to an element.
   * @param element The element to reveal
   * @param effect The effect to apply
   * 
   * Usage: applyEffectMac(getWidget(3).getElement(), "BlindUp");
   */
  public native void applyEffect(Element element, String effect) /*-{
    var ne = $wnd._nativeExtensions;
    $wnd._nativeExtensions = false;
    $wnd.Effect[effect](element);
    $wnd._nativeExtensions = ne;
  }-*/; 
  
  /**
   * This method creates and initializes the small gadget settings panel.
   */
  private void initLayout() {
    makeSettingsView();
    Window.addWindowCloseListener(this);
  }
  
  /**
   * This method creates a settings view and adds it to the web page.
   */
  private void makeSettingsView() {
    if (this.settingsPanel == null) {
      this.settingsPanel = new SettingsPanel();
      this.settingsPanel.getOkButton().addClickListener(this);
    }
    this.settingsFaceUp = Boolean.TRUE;
    RootPanel.get(WIDGETSLOT).add(this.settingsPanel);
  }
  
  /**
   * This method creates a twitter view and adds it to the web page.
   */
  private void makeTwitterView() {
    if (this.splitPane == null) {    
      this.splitPane = new VerticalSplitPanel();
      this.splitPane.setTopWidget(this.statusesPanel = new StatusesPanel());
      this.splitPane.setBottomWidget(this.entryPanel = new EntryPanel(this.statusesPanel));
      this.entryPanel.getOkImage().addClickListener(this);
      this.splitPane.setSplitPosition("70%");
    }
    this.settingsFaceUp = Boolean.FALSE;
    RootPanel.get(WIDGETSLOT).add(this.splitPane);
    this.statusesPanel.reset();
  }
  
  /**
   * This method flips between the settings panel and the data panel. 
   */
  private void flipPanels() {
    if (this.settingsFaceUp.booleanValue()) {
      RootPanel.get(WIDGETSLOT).remove(this.settingsPanel);
      makeTwitterView();
    }
    else {
      RootPanel.get(WIDGETSLOT).remove(this.splitPane);
      makeSettingsView();
    }
  }
  
  /**
   * This method displays the passed version in the UI.
   * @param version a string containing the version number 
   */
  private void setVersion(String version) {
    Window.setTitle("Hackystat: Hackerrific " + version);
    RootPanel.get("version").add(new HTML("<b>" + version + "</b>"));
  }
  
  /**
   * Check with the servlet to see if the host is valid.
   */
  private void rpcVersion() {
    RPCServiceFactory.getInstance().getService().version(new AsyncCallback() {
      public void onSuccess(Object result) {
        setVersion((String) result);
      }
  
      public void onFailure(Throwable caught) {
        if (caught instanceof com.google.gwt.user.client.rpc.InvocationException) {
          log(PRCERRORNAME, "Cannot invoke version request on servlet.");
        } 
        else {
          log(PRCERRORNAME, caught.toString());
        }
      }
    });
  }

  /**
   * This is the entry point method.
   */
  public void onModuleLoad() {
    rpcVersion();
    initLayout();
  }
  
  /**
   * Log this message in the reader display.
   * @param header the message header or subject
   * @param body the message body
   */
  private void log(String header, String body) {
    this.statusesPanel.log(header, body);
  }

  /** 
   * Respond to a window close event by logging out of Twitter.
   */
  public void onWindowClosed() {
    RPCServiceFactory.getInstance().getService().endSession(Cookies.getCookie("user"), 
      Cookies.getCookie("password"),
      new AsyncCallback()
      {
        public void onSuccess(Object result) {
          // widget closed now, nothing to do
        }

        public void onFailure(Throwable caught) {
          // widget closed now, nothing to do
        }
      });
  }

  /** 
   * Place holder for pre-handling a window closing event.
   * @return the string to be presented in a dialog box confirming closing.
   */
  public String onWindowClosing() {
    // TODO Auto-generated method stub
    return null;
  }

  /** 
   * Handle the click events for the flip panel UI elements (ok button and 'i' image).
   * @param sender the widget that was clicked on by the user.
   */
  public void onClick(Widget sender) {
    flipPanels();
  }
}


